<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>事件循环机制</title>
</head>
<body>
    <!-- JS是单线程执行

          作为浏览器脚本语言，JavaScript的主要用途是与用户互动，以及操作DOM。这决定了它只能是单线程，
          否则会带来很复杂的同步问题。比如，假定JavaScript同时有两个线程，
          一个线程在某个DOM节点上添加内容，另一个线程删除了这个节点，这时浏览器应该以哪个线程为准？


          单线程，顾名思义只有一条队伍，任务都是在排队等待使用CPU执行的。大多时候CPU处于空闲状态，例如IO设备（输入输出设备）很慢
         （比如Ajax操作从网络读取数据,操作页面DOM），不得不等着结果出来，再往下执行。JavaScript语言的设计者意识到，
          这时主线程完全可以不管IO设备，挂起处于等待中的任务，先运行排在后面的任务。等到IO设备返回了结果，再回过头，
          把挂起的任务继续执行下去。

            于是，所有任务可以分成两种：

            ①同步任务（synchronous）
            在主线程上排队执行的任务，只有前一个任务执行完毕，才能执行后一个任务；

            ②异步任务（asynchronous）
            不进入主线程、而进入"任务队列"（task queue）的任务，只有"任务队列"通知主线程，某个异步任务可以执行了，该任务才会进入主线程执行。

            ● setTimeout() 设置的异步延迟事件
            ● DOM 操作相关如布局和绘制事件
            ● 网络 I/O 如 AJAX 请求事件；
            ● 用户操作事件，如鼠标点击、键盘敲击。

            具体来说，异步执行的运行机制如下。

（同步执行也是如此，因为它可以被视为没有异步任务的异步执行。）
————————————————————————————————————————————
（1）所有同步任务都在主线程上执行，形成一个执行栈（execution context stack）。

（2）主线程之外，还存在一个"任务队列"（task queue）。只要异步任务有了运行结果，就在"任务队列"之中放置一个事件。

（3）一旦"执行栈"中的所有同步任务执行完毕（主线程空了），系统就会读取"任务队列"，看看里面有哪些事件。那些对应的异步任务，于是结束等待状态，进入执行栈，开始执行。

（4）主线程不断重复上面的第三步。
    
    
    -->
    <script>
         setTimeout(function(){    // 将定时器注册到JS引擎的相关模块内，定时器被触发会自动将回调函数添加到任务队列中
            console.log("第一个计时器");
        },0);

        function foo (){
            console.log("foo");
        }

        foo(); //执行栈中的函数调用结束会反复循环调用任务队列内的函数，依次执行




















    </script>
</body>
</html>